﻿#ifndef __UTILS_H__
#define __UTILS_H__

#pragma once

namespace DuiLib {
/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API STRINGorID
{
public:
    STRINGorID(LPCTSTR lpString);
    STRINGorID(unsigned int nID);

    LPCTSTR m_lpstr;
};

/////////////////////////////////////////////////////////////////////////////////////
//
class CDuiString;
class DUILIB_API CDuiPoint : public tagPOINT
{
public:
    CDuiPoint();
    CDuiPoint(const POINT &src);
    CDuiPoint(long x, long y);
    CDuiPoint(LPARAM lParam);
    CDuiPoint(LPCTSTR pstrValue);
    CDuiString ToString();
};

/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API CDuiSize : public tagSIZE
{
public:
    CDuiSize();
    CDuiSize(const SIZE &src);
    CDuiSize(const RECT rc);
    CDuiSize(long cx, long cy);
    CDuiSize(LPCTSTR pstrValue);
    CDuiString ToString();
};

/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API CDuiRect : public tagRECT
{
public:
    CDuiRect();
    CDuiRect(const RECT &src);
    CDuiRect(long iLeft, long iTop, long iRight, long iBottom);
    CDuiRect(LPCTSTR pstrValue);
    CDuiString ToString();

    int GetWidth() const;
    int GetHeight() const;
    void Empty();
    bool IsNull() const;
    void Join(const RECT &rc);
    void ResetOffset();
    void Normalize();
    void Offset(int cx, int cy);
    void Inflate(int cx, int cy);
    void Deflate(int cx, int cy);
    void Union(CDuiRect &rc);
};

/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API CDuiString
{
public:
    enum { MAX_LOCAL_STRING_LEN = 31 };

    CDuiString();
    CDuiString(const TCHAR ch);
    CDuiString(const CDuiString &src);
    CDuiString(LPCTSTR lpsz, int nLen = -1);
    ~CDuiString();
    CDuiString ToString();

    void Reserve(int nLen);     // 改变字符串最大存储空间
    void Empty();
    int GetLength() const;
    bool IsEmpty() const;
    TCHAR GetAt(int nIndex) const;
    CDuiString &Append(LPCTSTR pstr);
    void Assign(LPCTSTR pstr, int nLength = -1);
    LPCTSTR GetData() const;
    LPTSTR GetData(int nLen);

    void SetAt(int nIndex, TCHAR ch);
    operator LPCTSTR() const;

    TCHAR operator[](int nIndex) const;
    const CDuiString &operator=(const CDuiString &src);
    const CDuiString &operator=(const TCHAR ch);
    const CDuiString &operator=(LPCTSTR pstr);
#ifdef _UNICODE
    const CDuiString &operator=(LPCSTR lpStr);
    const CDuiString &operator+=(LPCSTR lpStr);
#else
    const CDuiString &operator=(LPCWSTR lpwStr);
    const CDuiString &operator+=(LPCWSTR lpwStr);
#endif
    CDuiString operator+(const CDuiString &src) const;
    CDuiString operator+(LPCTSTR pstr) const;
    const CDuiString &operator+=(const CDuiString &src);
    const CDuiString &operator+=(LPCTSTR pstr);
    const CDuiString &operator+=(const TCHAR ch);

    bool operator == (LPCTSTR str) const;
    bool operator != (LPCTSTR str) const;
    bool operator <= (LPCTSTR str) const;
    bool operator < (LPCTSTR str) const;
    bool operator >= (LPCTSTR str) const;
    bool operator > (LPCTSTR str) const;

    bool operator == (const CDuiString &str) const;
    bool operator != (const CDuiString &str) const;
    bool operator <= (const CDuiString &str) const;
    bool operator < (const CDuiString &str) const;
    bool operator >= (const CDuiString &str) const;
    bool operator > (const CDuiString &str) const;

    friend bool operator == (LPCTSTR str, const CDuiString &str2);
    friend bool operator != (LPCTSTR str, const CDuiString &str2);
    friend bool operator <= (LPCTSTR str, const CDuiString &str2);
    friend bool operator < (LPCTSTR str, const CDuiString &str2);
    friend bool operator >= (LPCTSTR str, const CDuiString &str2);
    friend bool operator > (LPCTSTR str, const CDuiString &str2);

    int Compare(LPCTSTR pstr) const;
    int CompareNoCase(LPCTSTR pstr) const;

    void MakeUpper();
    void MakeLower();

    CDuiString Left(int nLength) const;
    CDuiString Mid(int iPos, int nLength = -1) const;
    CDuiString Right(int nLength) const;

    int Find(TCHAR ch, int iPos = 0) const;
    int Find(LPCTSTR pstr, int iPos = 0) const;
    int ReverseFind(TCHAR ch) const;
    int Replace(LPCTSTR pstrFrom, LPCTSTR pstrTo);

    int __cdecl Format(LPCTSTR pstrFormat, ...);
    int __cdecl SmallFormat(LPCTSTR pstrFormat, ...);

protected:
    LPTSTR m_pstr;
    TCHAR m_szBuffer[MAX_LOCAL_STRING_LEN + 1];
};

inline bool operator == (LPCTSTR str, const CDuiString &str2)
{
    return (str2.Compare(str) == 0);
}
inline bool operator != (LPCTSTR str, const CDuiString &str2)
{
    return (str2.Compare(str) != 0);
}
inline bool operator <= (LPCTSTR str, const CDuiString &str2)
{
    return (str2.Compare(str) <= 0);
}
inline bool operator < (LPCTSTR str, const CDuiString &str2)
{
    return (str2.Compare(str) < 0);
}
inline bool operator >= (LPCTSTR str, const CDuiString &str2)
{
    return (str2.Compare(str) >= 0);
}
inline bool operator > (LPCTSTR str, const CDuiString &str2)
{
    return (str2.Compare(str) > 0);
}

/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API CDuiPtrArray
{
public:
    CDuiPtrArray(int iPreallocSize = 0);
    CDuiPtrArray(const CDuiPtrArray &src);
    ~CDuiPtrArray();

    void Empty();
    void Resize(int iSize);
    bool IsEmpty() const;
    int Find(LPVOID pData) const;
    bool Add(LPVOID pData);
    bool SetAt(int iIndex, LPVOID pData);
    bool InsertAt(int iIndex, LPVOID pData);
    bool Remove(int iIndex, int iCount = 1);
    int GetSize() const;
    LPVOID *GetData();

    LPVOID GetAt(int iIndex) const;
    LPVOID operator[](int nIndex) const;

protected:
    LPVOID *m_ppVoid;
    int m_nCount;
    int m_nAllocated;
};


/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API CDuiValArray
{
public:
    CDuiValArray(int iElementSize, int iPreallocSize = 0);
    ~CDuiValArray();

    void Empty();
    bool IsEmpty() const;
    bool Add(LPCVOID pData);
    bool Remove(int iIndex,  int iCount = 1);
    bool Remove(LPCVOID pData);
    int GetSize() const;
    LPVOID GetData();

    LPVOID GetAt(int iIndex) const;
    LPVOID operator[](int nIndex) const;

protected:
    LPBYTE m_pVoid;
    int m_iElementSize;
    int m_nCount;
    int m_nAllocated;
};

/////////////////////////////////////////////////////////////////////////////////////
//

struct TITEM;
class DUILIB_API CDuiStringPtrMap
{
public:
    CDuiStringPtrMap(int nSize = 83);
    ~CDuiStringPtrMap();

    void Resize(int nSize = 83); // 会销毁已存储的数据
    LPVOID Find(LPCTSTR key, bool optimize = true) const;
    bool Insert(LPCTSTR key, LPVOID pData);
    LPVOID Set(LPCTSTR key, LPVOID pData);
    bool Remove(LPCTSTR key);
    void RemoveAll();
    int GetSize() const;
    LPCTSTR GetAt(int iIndex) const;
    LPCTSTR operator[](int nIndex) const;

protected:
    TITEM **m_aT;
    int m_nBuckets;
    int m_nCount;
};

/////////////////////////////////////////////////////////////////////////////////////
//

class DUILIB_API CWaitCursor
{
public:
    CWaitCursor();
    ~CWaitCursor();

protected:
    HCURSOR m_hOrigCursor;
};

/////////////////////////////////////////////////////////////////////////////////////
//

class CVariant : public VARIANT
{
public:
    CVariant()
    {
        VariantInit(this);
    }
    CVariant(int i)
    {
        VariantInit(this);
        this->vt = VT_I4;
        this->intVal = i;
    }
    CVariant(float f)
    {
        VariantInit(this);
        this->vt = VT_R4;
        this->fltVal = f;
    }
    CVariant(LPOLESTR s)
    {
        VariantInit(this);
        this->vt = VT_BSTR;
        this->bstrVal = s;
    }
    CVariant(IDispatch *disp)
    {
        VariantInit(this);
        this->vt = VT_DISPATCH;
        this->pdispVal = disp;
    }

    ~CVariant()
    {
        VariantClear(this);
    }
};

}// namespace DuiLib

#endif // __UTILS_H__
